package com.example.ljdemo.infrastructure.security;

import com.example.ljdemo.infrastructure.security.jwt.JwtAccessDeniedHandler;
import com.example.ljdemo.infrastructure.security.jwt.JwtAuthenticationEntryPoint;
import com.example.ljdemo.infrastructure.security.jwt.JwtAuthenticationTokenFilter;
import com.example.ljdemo.infrastructure.security.jwt.JwtTokenUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * SpringSecurity的配置类，因为加上了验证码登陆，所以要在配置的地方进行配置；
 * 加上自己客制化的各种Handler，因为普遍的采用前后端分离，所以全部改为返回统一的数据结构；由前端做跳转；
 * 默认加上Okta相关的登陆，如果不需要Okta集成，去掉相关的类即可；
 * @author jingjing.dong
 * @since 2021/4/8-14:31
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
    private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    private final JwtTokenUtils jwtTokenUtils;
    public SecurityConfig(JwtAccessDeniedHandler jwtAccessDeniedHandler, JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint, JwtTokenUtils jwtTokenUtils) {
        this.jwtAccessDeniedHandler = jwtAccessDeniedHandler;
        this.jwtAuthenticationEntryPoint = jwtAuthenticationEntryPoint;
        this.jwtTokenUtils = jwtTokenUtils;
    }

    /**
     * 定义路径 不被Security保护
     * 包括验证码、静态资源、actuator 等等
     */
    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/static/**","/css/**","/js/**","/img/**","/fonts/**","/favicon.ico",
                "/verifyCode","/actuator/**","/mail/*");
    }
    /*@Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(verificationCodeAuthProvider);
    }*/

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                // 禁用 CSRF
                .csrf().disable()

                // 授权异常
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .accessDeniedHandler(jwtAccessDeniedHandler)

                // 防止iframe 造成跨域
//                .and()
//                .headers()
//                .frameOptions()
//                .disable()
                .and().cors()
                // 不创建会话
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

                .and()
                .authorizeRequests()

                // 放行静态资源
                .antMatchers(
                        HttpMethod.GET,
                        "/*.html",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/file/**",
                        "/webSocket/**"
                ).permitAll()

                // 放行swagger
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/*/api-docs").permitAll()

                // 放行文件访问
                .antMatchers("/file/**").permitAll()

                // 放行druid
                .antMatchers("/druid/**").permitAll()

                // 放行OPTIONS请求
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()

                //允许匿名及登录用户访问
                .antMatchers(
                        "/locale/test",
                        "/excel/exportExcel",
                        "/qyWeChat/getAccess",
                        "/qyWeChat/outh2",
                        "/qyWeChat/getcode",
                        "/login",
                        "/mobileemployeelist/*",
                        "/model/erp-user/login",
                        "/error/**").permitAll()

                // 所有请求都需要认证
                .anyRequest().authenticated();

        // 禁用缓存
        http.headers().cacheControl();

        // 添加JWT filter
        http.apply(new TokenConfigurer(jwtTokenUtils));


    }
    /*private OktaAuthenticationFilter getOktaAuthenticationFilter(){
        OktaAuthenticationFilter oktaAuthenticationFilter = new OktaAuthenticationFilter();
        oktaAuthenticationFilter.setAuthenticationManager(new ProviderManager(oktaAuthProvider));
        oktaAuthenticationFilter.setAuthenticationSuccessHandler(new CustomAuthenticationSuccessHandler());
        return oktaAuthenticationFilter;
    }
    private QywechatAuthenticationFilter getQywechatAuthenticationFilter(){
        QywechatAuthenticationFilter qywechatAuthenticationFilter = new QywechatAuthenticationFilter();
        qywechatAuthenticationFilter.setAuthenticationManager(new ProviderManager(qywechatAuthProvider));
        qywechatAuthenticationFilter.setAuthenticationSuccessHandler(new QywechatAuthenticationSuccessHandler());
        return qywechatAuthenticationFilter;
    }*/

    public class TokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

        private final JwtTokenUtils jwtTokenUtils;

        public TokenConfigurer(JwtTokenUtils jwtTokenUtils){

            this.jwtTokenUtils = jwtTokenUtils;
        }

        @Override
        public void configure(HttpSecurity http) {
            JwtAuthenticationTokenFilter customFilter = new JwtAuthenticationTokenFilter(jwtTokenUtils);
            http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
        }
    }



}
